from os.path import split
from urlparse import urlparse

from logging import getLogger

from nevow.athena import LiveElement, expose
from nevow.flat import flatten
from nevow.loaders import stan, xmlstr
from nevow import tags

from sqlalchemy import create_engine

from zope.component import getGlobalSiteManager

from meercat.harvester.base.interfaces import IHarvester, IQueriableHarvester
from meercat.harvester.base.sources import FTPSource
from meercat.harvester.metalib.harvester import MetalibHarvester
from meercat.harvester.sfx.harvester import SfxHarvester
from meercat.harvester.voyager import VoyagerHarvester



log = getLogger('meercat.server.nevow.elements.harvester')

registry = getGlobalSiteManager()

class HarvesterList(LiveElement):
    jsClass = u'Meercat.Harvester.List'
    
    docFactory = stan(tags.div(render=tags.directive('liveElement'))[
        tags.ul(class_='HarvesterListActions actionList')[
            tags.li()[
                tags.a(href='#',
                       onclick="Nevow.Athena.Widget.get(this).addHarvesterElement(); return false;")['Add Harvester']],
            tags.li()[
                tags.a(href='#',
                       onclick="Nevow.Athena.Widget.get(this).refresh(); return false;")['Refresh List']]],
        tags.ul(class_='HarvesterList'),])
    
    @expose
    def getHarvesters(self):
        log.info('%s.getHarvesters()' % (str(self),))
        return map(lambda t: t[0], registry.getUtilitiesFor(IHarvester))
                
    @expose
    def deleteHarvester(self, name):
        log.info('%s.deleteHarvester()' % (str(self),))
        return registry.unregisterUtility(name=name, provided=IHarvester)
    
    @expose
    def getAddHarvesterElement(self):
        log.info('%s.getAddHarvesterElement()' % (str(self),))
        e = HarvesterAddForm()
        e.setFragmentParent(self)
        
        return e
                
class HarvesterAddForm(LiveElement):
    jsClass = u'Meercat.Harvester.Add'
    
    docFactory = stan(tags.div(class_='yui-g',
                               render=tags.directive('liveElement'))[
        tags.h1()['Add a Harvester'],
        tags.a(href='#',onclick='Nevow.Athena.Widget.get(this).remove(); return false;')['Close'],
        tags.form()[
            tags.ul()[
                tags.li()['Name: ', tags.input(name="name", type="text")],
                tags.li()['Source: ', tags.input(name='source', type='text')],
                tags.li()['Type: ',
                    tags.select(name="type")[
                        tags.option(value="metalib")['Metalib'],
                        tags.option(value="sfx")['SFX'],
                        tags.option(value="voyager")['Voyager']]],
                tags.li()['Schema: ', tags.input(name="schema", type="text")]],
            tags.input(value="Add Harvester", type="button",
                onclick="Nevow.Athena.Widget.get(this).addHarvester();",)]])
    
    @expose
    def createHarvester(self, name, source, harvester, schema):
        name = name.strip()
        source = source.strip()
        
        if not name:
            raise ValueError('A name is required')
        
        if not source:
            source = name
        
        if harvester in ['sfx','metalib']:
            schema = urlparse(schema)
            # other is a dictionary of fields based on urlparsed items from schema..
            
            if schema.scheme == 'ftp':
                other = {}
                if schema.username:
                    other['user'] = schema.username
                if schema.password:
                    other['passwd'] = schema.password
                if schema.hostname and schema.port:
                    other['host'] = '%s:%s' % (schema.hostname, str(schema.port))
                elif schema.hostname:
                    other['host'] = schema.hostname
                
                folder, filename = split(schema.path)
                folder = folder[1:]
                log.info('Create ftp source: folder=%s, filename pattern=%s' % (folder, filename,))
                import re
                sourcef = FTPSource(folder=folder,
                                    filter=lambda x: re.match(filename, x),
                                    **other)
            else:
                raise Exception('%s is an unsupported schema' % (str(schema.scheme),))
                        
            if harvester == 'sfx':
                harvester = SfxHarvester(source_function=sourcef, source=source)
            else:
                harvester = MetalibHarvester(source_function=sourcef, source=source)
        
        elif harvester == 'voyager':
            harvester = VoyagerHarvester(source, schema, encoding='utf-8')
        else:
            raise Exception('Invalid harvester type: %s' % (str(harvester)))
        
        registry.registerUtility(component=harvester, name=name,
                                 provided=IHarvester)
        
        return True
